package org.yaac.shared.egql;

import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.Maps.newHashMap;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * not like Result, Response will be returned immediately
 * so that client side can initialize result panels based on response content
 * 
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class Response implements Serializable {

	public List<String> getImmediateStmts() {
		return immediateStmts;
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * if not started, then there must be something wrong
	 */
	private ResponseStatus status;
	
	/**
	 * for general syntax recognition error, attach message generated from ANTLR
	 * 
	 * not empty ONLY when status = SYNTAX_ERROR
	 */
	private String message;
	
	/**
	 * error code
	 * 
	 * not empty ONLY when status = LOGICAL_ERROR
	 */
	private String errorCode;
	
	/**
	 * response map from pipeline id to raw statement
	 */
	private Map<String, String> responseMap;

	/**
	 * statement executed immediately in the RPC call
	 * 
	 *  at the moment this include : insert
	 */
	private List<String> immediateStmts;
	
	/**
	 * 
	 */
	public Response(){
		super();
		this.responseMap = newHashMap();
		this.immediateStmts = newLinkedList();
	}

	/**
	 * @param id
	 * @param rawStmt
	 * @return
	 */
	public Response add(String id, String rawStmt) {
		this.responseMap.put(id, rawStmt);
		return this;
	}
	
	public Response immediateStmt(String rawStmt) {
		this.immediateStmts.add(rawStmt);
		return this;
	}
	
	/**
	 * @return
	 */
	public Map<String, String> getResponseMap() {
		return responseMap;
	}

	public ResponseStatus getStatus() {
		return status;
	}

	public void setStatus(ResponseStatus status) {
		this.status = status;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((errorCode == null) ? 0 : errorCode.hashCode());
		result = prime * result + ((message == null) ? 0 : message.hashCode());
		result = prime * result + ((responseMap == null) ? 0 : responseMap.hashCode());
		result = prime * result + ((status == null) ? 0 : status.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Response other = (Response) obj;
		if (errorCode == null) {
			if (other.errorCode != null)
				return false;
		} else if (!errorCode.equals(other.errorCode))
			return false;
		if (message == null) {
			if (other.message != null)
				return false;
		} else if (!message.equals(other.message))
			return false;
		if (responseMap == null) {
			if (other.responseMap != null)
				return false;
		} else if (!responseMap.equals(other.responseMap))
			return false;
		if (status != other.status)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Response [status=" + status + ", message=" + message + ", errorCode=" + errorCode + ", responseMap="
				+ responseMap + "]";
	}
}
